package com.yk.networking;

import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.UUID;

public class YKNetworking {

    private YKNetworkingRequest request;

    public String prefixUrl = null;

    public Map<String,YKNetworkingRequest> requestDictionary = new HashMap<>();

    public YKNetworkingConfigHandleResponse handleResponse = null;

    public YKNetworkingConfigDynamicParamsConfig dynamicParamsConfig = null;

    public YKNetworkingConfigDynamicHeaderConfig dynamicHeaderConfig = null;

    public Map<String, String> defaultHeader = null;

    public Map<String, String> defaultParams = null;

    private Map<String, String> inputHeader = null;

    private Map<String, String> inputParams = null;

    private void setRequest(YKNetworkingRequest request) {
        this.request = request;
    }

    private YKNetworkingRequest getRequest() {
        if (request == null){
            request = new YKNetworkingRequest();



            if (YKNetworkingConfig.getInstance().defaultHeader != null) {
                Iterator<String> it = YKNetworkingConfig.getInstance().defaultHeader.keySet().iterator();
                while (it.hasNext()){
                    String key = it.next();
                    request.header.put(key,YKNetworkingConfig.getInstance().defaultHeader.get(key));
                }
            }

            if (YKNetworkingConfig.getInstance().defaultParams != null) {
                Iterator<String> it = YKNetworkingConfig.getInstance().defaultParams.keySet().iterator();
                while (it.hasNext()){
                    String key = it.next();
                    request.params.put(key,YKNetworkingConfig.getInstance().defaultParams.get(key));
                }
            }

            if (this.defaultHeader != null) {
                Iterator<String> it = this.defaultHeader.keySet().iterator();
                while (it.hasNext()){
                    String key = it.next();
                    request.header.put(key,this.defaultHeader.get(key));
                }
            }

            if (this.defaultParams != null) {
                Iterator<String> it = this.defaultParams.keySet().iterator();
                while (it.hasNext()){
                    String key = it.next();
                    request.params.put(key,this.defaultParams.get(key));
                }
            }
        }
        return request;
    }

    public YKNetworking() {

    }

    public YKNetworking url(String url) {
        String urlStr;

        if (url.startsWith("http://") || url.startsWith("https://")){
            this.getRequest().urlStr = url;
            return this;
        }
        String prefix = "";
        if (this.prefixUrl != null){
            prefix = this.prefixUrl;
        }else {
            prefix = YKNetworkingConfig.getInstance().defaultPrefixUrl;
        }
        if (prefix == null || prefix.length() == 0){
            this.getRequest().urlStr = url;
            return this;
        }

        // 处理重复斜杠的问题
        String removeSlash = null;
        if (prefix.length() >0 && url.length() >0){
            String lastCharInPrefix = prefix.substring(prefix.length()-1);
            String firstCharInUrl = url.substring(0,1);
            if (lastCharInPrefix.equals("/") && firstCharInUrl.equals("/")){
                removeSlash = prefix.substring(0,prefix.length()-1);
            }
        }
        if (removeSlash != null){
            prefix = removeSlash;
        }

        urlStr = new StringBuffer().append(prefix).append(url).toString();
        this.getRequest().urlStr = urlStr;
        return this;
    }

    public YKNetworking method(YKNetworkingConst.YKNetworkingRequestMethod method) {
        this.getRequest().method = method;
        return this;
    }

    public YKNetworking params(Map<String,String> params) {

        this.inputParams = params;
        if (params != null) {
            Iterator<String> it = params.keySet().iterator();
            while (it.hasNext()){
                String key = it.next();
                request.params.put(key,params.get(key));
            }
        }

        return this;
    }

    public YKNetworking header(Map<String,String> header) {
        this.inputHeader = header;
        if (header != null) {
            Iterator<String> it = header.keySet().iterator();
            while (it.hasNext()){
                String key = it.next();
                request.header.put(key,header.get(key));
            }
        }

        return this;
    }

    public YKNetworking disableDynamicParams() {
        this.getRequest().disableDynamicParams = true;
        return this;
    }

    public YKNetworking disableDynamicHeader() {
        this.getRequest().disableDynamicHeader = true;
        return this;
    }

    public YKNetworking disableHandleResponse() {
        this.getRequest().disableHandleResponse = true;
        return this;
    }

    /** 设置下载路径
     *  设置后默认调用下载方式
     *  **/
    public YKNetworking downloadDestPath(String destPath) {
        this.getRequest().destPath = destPath;
        this.getRequest().isDownload = true;
        return this;
    }

    public YKNetworking progress(YKNetworkingProgressCallBack progressCallBack) {
        this.getRequest().progressCallBack = progressCallBack;
        return this;
    }

    public YKNetworking mockData(Object mockData) {
        this.getRequest().mockData = mockData;
        return this;
    }

    public YKNetworking fileFieldName(String fileFieldName) {
        this.getRequest().fileFieldName = fileFieldName;
        return this;
    }
    
    /** 设置上传数据
     *  设置后默认调用上传方式
     *  **/
    public YKNetworking uploadData(byte[] data, String fileName, String mimeType, String formDataName) {
        this.getRequest().uploadFileData = data;
        this.getRequest().uploadName = fileName;
        this.getRequest().uploadMimeType = mimeType;
        this.getRequest().formDataName = formDataName;
        this.getRequest().isUpload = true;
        return this;
    }


    public YKNetworking GET(String url) {
        return this.method(YKNetworkingConst.YKNetworkingRequestMethod.YKNetworkingRequestMethodGET).url(url);
    }

    public YKNetworking POST(String url) {
        return this.method(YKNetworkingConst.YKNetworkingRequestMethod.YKNetworkingRequestMethodPOST).url(url);
    }

    public YKNetworking PATCH(String url){
        return this.method(YKNetworkingConst.YKNetworkingRequestMethod.YKNetworkingRequestMethodPATCH).url(url);
    }

    public void execute(YKNetworkingComplateCallBack callBack) {
        YKNetworking weaknetworking = this;
        try {
            YKNetworkingRequest requestCopy = (YKNetworkingRequest) weaknetworking.getRequest().clone();
            Boolean canContinue = weaknetworking.handleConfigWithRequest(requestCopy);
            if (!canContinue) {
                callBack.onComplate(new YKNetworkingRequest(), new YKNetworkingResponse(), new Error("不允许请求"));
                weaknetworking.saveTask(weaknetworking.request, new YKNetworkingResponse(), false);
                return;
            }

            if (requestCopy.isUpload) {
                YKBaseNetworking.uploadCall(requestCopy, new YKBaseNetworkingResult() {
                    @Override
                    public void success(YKNetworkingRequest request, YKNetworkingResponse response) {
                        callBack.onComplate(request,response,null);
                    }

                    @Override
                    public void failure(YKNetworkingRequest request, Boolean isCache, Object responseObject, Error error) {
                        callBack.onComplate(request,new YKNetworkingResponse(),error);
                    }
                });
            } else if (requestCopy.isDownload) {
                YKBaseNetworking.downloadCall(requestCopy, new YKBaseNetworkingResult() {
                    @Override
                    public void success(YKNetworkingRequest request, YKNetworkingResponse response) {
                        callBack.onComplate(request,response,null);
                    }

                    @Override
                    public void failure(YKNetworkingRequest request, Boolean isCache, Object responseObject, Error error) {
                        callBack.onComplate(request,new YKNetworkingResponse(),error);
                    }
                });
            } else {
                YKBaseNetworking.requestWithRequest(requestCopy, new YKBaseNetworkingResult() {
                    @Override
                    public void success(YKNetworkingRequest request, YKNetworkingResponse response) {
                        callBack.onComplate(request,response,null);
                    }

                    @Override
                    public void failure(YKNetworkingRequest request, Boolean isCache, Object responseObject, Error error) {
                        callBack.onComplate(request,new YKNetworkingResponse(), error);
                    }
                });
            }

        }catch (Exception exception) {
            callBack.onComplate(new YKNetworkingRequest(), new YKNetworkingResponse(), new Error(exception.getMessage()));
        }
    }

//    public Observable<Object> execute(){
//
//        YKNetworking weaknetworking = this;
//        Observable<Object> observable = Observable.create(new ObservableOnSubscribe<Object>() {
//            @Override
//            public void subscribe(@io.reactivex.rxjava3.annotations.NonNull ObservableEmitter<Object> emitter) throws Throwable {
//                try
//                {
//                    YKNetworkingRequest requestCopy = (YKNetworkingRequest) weaknetworking.getRequest().clone();
//                    Boolean canContinue = weaknetworking.handleConfigWithRequest(requestCopy);
//                    if (!canContinue){
//                        emitter.onError(new Error("不允许请求"));
//                        emitter.onComplete();
//                        weaknetworking.saveTask(weaknetworking.request, new YKNetworkingResponse(),false);
//                        return;
//                    }
//
//                    YKBaseNetworking.requestWithRequest(requestCopy, new YKNetworkingProgressCallBack() {
//                        @Override
//                        public void progress(float progress) {
//                            if (requestCopy.progressCallBack != null) {
//                                requestCopy.progressCallBack.progress(progress);
//                            }
//                        }
//                    }, new YKBaseNetworkingResult() {
//                        @Override
//                        public void success(YKNetworkingRequest request, YKNetworkingResponse response) {
//                            Error error = null;
//                            if (weaknetworking.handleResponse != null && !request.disableHandleResponse){
//                                error = weaknetworking.handleResponse.handleResponse(request, response);
//                                if (error == null) {
//                                    emitter.onNext(response.rawData);
//                                }else {
//                                    emitter.onError(error);
//                                }
//                            }else {
//                                emitter.onNext(response.rawData);
//                            }
//                            emitter.onComplete();
//                            weaknetworking.saveTask(request, response, (error != null));
//                        }
//
//                        @Override
//                        public void failure(YKNetworkingRequest request, Boolean isCache, Object responseObject, Error error) {
//                            YKNetworkingResponse response = new YKNetworkingResponse();
//                            response.rawData = error;
//                            emitter.onError(error);
//                            emitter.onComplete();
//                            weaknetworking.saveTask(request, response, true);
//                        }
//                    });
//                    return;
//                }catch (Exception exception) {
//                    Error error = new Error(exception.toString());
//                    emitter.onError(error);
//                    emitter.onComplete();
//                    weaknetworking.saveTask((YKNetworkingRequest) weaknetworking.getRequest(), new YKNetworkingResponse(), true);
//                }finally {
//                    weaknetworking.request = null;
//                }
//            }
//        });
//
//        return observable;
//
//    }
//
//
//    public Observable<Object> executeDownload()
//    {
//        YKNetworking weaknetworking = this;
//        Observable<Object> downloadObservalbe = Observable.create(new ObservableOnSubscribe<Object>() {
//            @Override
//            public void subscribe(@io.reactivex.rxjava3.annotations.NonNull ObservableEmitter<Object> emitter) throws Throwable {
//
//                try {
//                    YKNetworkingRequest requestCopy = (YKNetworkingRequest) weaknetworking.getRequest().clone();
//                    Boolean canContinue = weaknetworking.handleConfigWithRequest(requestCopy);
//                    if (!canContinue) {
//                        emitter.onError(new Error("不允许请求"));
//                        emitter.onComplete();
//                        weaknetworking.saveTask(weaknetworking.request, new YKNetworkingResponse(),false);
//                        return;
//                    }
//
//                    YKBaseNetworking.downloadCall(requestCopy, new YKNetworkingProgressCallBack() {
//                        @Override
//                        public void progress(float progress) {
//                            if (requestCopy.progressCallBack != null) {
//                                requestCopy.progressCallBack.progress(progress);
//                            }
//                        }
//                    }, new YKBaseNetworkingResult() {
//                        @Override
//                        public void success(YKNetworkingRequest request, YKNetworkingResponse response) {
//                            Error error = null;
//                            if (weaknetworking.handleResponse != null && !request.disableHandleResponse){
//                                error = weaknetworking.handleResponse.handleResponse(request, response);
//                                if (error == null) {
//                                    emitter.onNext(response.rawData);
//                                }else {
//                                    emitter.onError(error);
//                                }
//                            }else {
//                                emitter.onNext(response.rawData);
//                            }
//                            emitter.onComplete();
//                            weaknetworking.saveTask(request, response, (error != null));
//                        }
//
//                        @Override
//                        public void failure(YKNetworkingRequest request, Boolean isCache, Object responseObject, Error error) {
//                            YKNetworkingResponse response = new YKNetworkingResponse();
//                            response.rawData = error;
//                            emitter.onError(error);
//                            emitter.onComplete();
//                            weaknetworking.saveTask(request, response, true);
//                        }
//                    });
//
//
//                }catch (Exception exception) {
//                    Error error = new Error(exception.toString());
//                    emitter.onError(error);
//                    emitter.onComplete();
//                    weaknetworking.saveTask((YKNetworkingRequest) weaknetworking.getRequest(), new YKNetworkingResponse(), true);
//                }finally {
//                    weaknetworking.request = null;
//                }
//            }
//        });
//        return downloadObservalbe;
//    }
//
//    public Observable<Object> executeUpload() {
//        YKNetworking weaknetworking = this;
//        Observable<Object> uploadObservable = Observable.create(new ObservableOnSubscribe<Object>() {
//            @Override
//            public void subscribe(@io.reactivex.rxjava3.annotations.NonNull ObservableEmitter<Object> emitter) throws Throwable {
//                try {
//                    YKNetworkingRequest requestCopy = (YKNetworkingRequest) weaknetworking.getRequest().clone();
//                    Boolean canContinue = weaknetworking.handleConfigWithRequest(requestCopy);
//                    if (!canContinue) {
//                        emitter.onError(new Error("不允许请求"));
//                        emitter.onComplete();
//                        weaknetworking.saveTask(weaknetworking.request, new YKNetworkingResponse(),false);
//                        return;
//                    }
//
//                    YKBaseNetworking.uploadCall(requestCopy, new YKNetworkingProgressCallBack() {
//                        @Override
//                        public void progress(float progress) {
//                            if (requestCopy.progressCallBack != null) {
//                                requestCopy.progressCallBack.progress(progress);
//                            }
//                        }
//                    }, new YKBaseNetworkingResult() {
//                        @Override
//                        public void success(YKNetworkingRequest request, YKNetworkingResponse response) {
//
//                            Error error = null;
//                            if (weaknetworking.handleResponse != null && !request.disableHandleResponse){
//                                error = weaknetworking.handleResponse.handleResponse(request, response);
//                                if (error == null) {
//                                    emitter.onNext(response.rawData);
//                                }else {
//                                    emitter.onError(error);
//                                }
//                            }else {
//                                emitter.onNext(response.rawData);
//                            }
//                            emitter.onComplete();
//                            weaknetworking.saveTask(request, response, (error != null));
//
//                        }
//
//                        @Override
//                        public void failure(YKNetworkingRequest request, Boolean isCache, Object responseObject, Error error) {
//                            YKNetworkingResponse response = new YKNetworkingResponse();
//                            response.rawData = error;
//                            emitter.onError(error);
//                            emitter.onComplete();
//                            weaknetworking.saveTask(request, response, true);
//                        }
//                    });
//                }catch (Exception exception) {
//                    Error error = new Error(exception.toString());
//                    emitter.onError(error);
//                    emitter.onComplete();
//                    weaknetworking.saveTask((YKNetworkingRequest) weaknetworking.getRequest(), new YKNetworkingResponse(), true);
//                }finally {
//                    weaknetworking.request = null;
//                }
//            }
//        });
//        return uploadObservable;
//    }

    private Boolean handleConfigWithRequest(YKNetworkingRequest request) throws CloneNotSupportedException {
        if (request.name == null || request.name.length() > 0) {
            request.name = UUID.randomUUID().toString();
        }

        try {

            YKNetworkingConfig config = YKNetworkingConfig.getInstance();

            //处理默认头部和默认参数
            if (!request.disableDynamicHeader && (this.dynamicHeaderConfig != null)) {
                Map<String, String> dynamicHeader = null;
                if (this.dynamicHeaderConfig != null) {
                    dynamicHeader = this.dynamicHeaderConfig.dynamicHeaderConfig(request);
                }
                if (dynamicHeader != null) {
                    Iterator<String> it = dynamicHeader.keySet().iterator();
                    while (it.hasNext()) {
                        String key = it.next();
                        if (this.inputHeader != null && !this.inputHeader.containsKey(key)) {
                            request.header.put(key,dynamicHeader.get(key));
                        }else  {
                            request.header.put(key,dynamicHeader.get(key));
                        }

                    }
                }
            }

            if (!request.disableDynamicParams && (this.dynamicParamsConfig != null)) {
                Map<String, String> dynamicParams = null;
                if (this.dynamicParamsConfig != null) {
                    dynamicParams = this.dynamicParamsConfig.dynamicParamsConfig(request);
                }
                if (dynamicParams != null) {
                    Iterator<String> it = dynamicParams.keySet().iterator();
                    while (it.hasNext()) {
                        String key = it.next();
                        if (this.inputParams != null && !this.inputParams.containsKey(key)) {
                            request.params.put(key,dynamicParams.get(key));
                        }else  {
                            request.params.put(key,dynamicParams.get(key));
                        }
                    }
                }
            }


            this.requestDictionary.put(request.name,request);

            return true;
        }catch (Exception ex) {
            throw ex;
        }
    }

    public void cancelAllRequest()
    {
        for (String name:this.requestDictionary.keySet()) {
            YKNetworkingRequest request = this.requestDictionary.get(name);
            if (request.call!=null) {
                request.call.cancel();
            }
        }
        this.requestDictionary.clear();
    }

    public void cancelRequestWithName(String name) {
        if (this.requestDictionary.keySet().contains(name)) {
            YKNetworkingRequest request = this.requestDictionary.get(name);
            if (request.call!=null) {
                request.call.cancel();
            }
            this.requestDictionary.remove(name);
        }
    }

    private void saveTask(YKNetworkingRequest request, YKNetworkingResponse response, Boolean isException) {
        if (YKNetworkingConfig.getInstance().cacheRequest != null) {
            YKNetworkingConfig.getInstance().cacheRequest.cacheRequest(request, response, isException);
        }
    }

}
